export default {
    name: "zsmbfield",
    props: {
        modelValue: Boolean,
        fields: {
            type: Array,
            default: []
        },
        backgroundUrl: String,
        xmid: [String, Number],
        xmlist: {
            type: Array,
            default: []
        },
        fonts: {
            type: Array,
            default: []
        }
    },
    emits: ['update:modelValue', 'update'],
    setup(props, { emit }) {
        const router = VueRouter.useRouter();
        const { smartSpeak } = inject('speech'); //语音
		// 响应式状态
		const visible = computed({
			get: () => props.modelValue,
			set: (val) => emit('update:modelValue', val)
		})
		const canvasContainer = ref(null);
		const canvasSize = reactive({width: 0,height: 0});
		const selectedIndex = ref(-1);
		const activePanel = ref(['field-props']);
		const zdoptions = ref([]);
		const bgsx = ref({});
		const usedValues = reactive(new Set())
		// 字段配置数据
		const localFields = reactive([...props.fields])
        // 计算属性以保持引用关系
        const currentField = computed({
            get: () => selectedIndex.value > -1 ? localFields[selectedIndex.value] : {},
            set: (val) => {
                if (selectedIndex.value > -1) {
                    Object.assign(localFields[selectedIndex.value], val)
                }
            }
        })
		// 拖拽状态
		const dragState = reactive({
			isDragging: false,
			isResizing: false,
			startX: 0,
			startY: 0,
			originX: 0,
			originY: 0,
			scrollLeft: 0,
			scrollTop: 0
		})
		
        onMounted(() => window.addEventListener('keydown', handleKeydown))
        onBeforeUnmount(() => window.removeEventListener('keydown', handleKeydown))

		// 计算属性
		const canvasStyle = computed(() => ({
			width: `${canvasSize.width}px`,
			height: `${canvasSize.height}px`,
			background: `url(${props.backgroundUrl}) no-repeat center/contain`
		}))

        // 是否图片字段
		const isImageField = computed(() =>
			currentField.value.name && bgsx.value.fields?.[currentField.value.name]?.type == 'image'
		)

		// 方法
        const getFieldStyle = (field) => {
            const fontFamily = systemFontMap[field.fontfamily] || systemFontMap.默认;
            return {
                transform: `translate(${field.x}px, ${field.y}px)`,
                color: field.fontcolor,
                fontSize: `${field.fontsize}px`,
                fontFamily: fontFamily,
                width: isImageField.value ? `${field.width}px` : (field.textwidth ? `${field.textwidth}px` : 'auto'),
                height: isImageField.value ? `${field.height}px` : 'auto',
                cursor: dragState.isDragging ? 'grabbing' : 'grab',
                position: 'absolute',
                left: 0,  // 固定为0，通过transform定位
                top: 0,
                lineHeight: `${field.rowheight}px`
            }
        }

		// 初始化画布尺寸
        const initCanvasSize = () => {
            let isActive = true; // 加载状态锁
            let img = new Image();
            img.onload = () => {
                if (!isActive) return;
                canvasSize.width = img.naturalWidth;
                canvasSize.height = img.naturalHeight;
                nextTick(() => {
                    if (canvasContainer.value) {
                        canvasContainer.value.scrollLeft = img.naturalWidth/2 - 200;
                        canvasContainer.value.scrollTop = img.naturalHeight/2 - 150;
                    }
                });
            };
            img.onerror = () => {
                if (!isActive) return;
                // 设置安全默认值
                canvasSize.width = 800; 
                canvasSize.height = 600;
                ElMessage.error('背景图加载失败，请检查URL有效性');
            };
            // 强制浏览器重新请求（解决缓存问题）
            img.src = props.backgroundUrl + '?t=' + Date.now();
            // 组件卸载时彻底清理
            onBeforeUnmount(() => {
                isActive = false;
                img.onload = null;
                img.onerror = null;
                img.src = '';
                img = null;
            });
        };

        const startFieldDrag = (index, e) => {
            e.stopPropagation()
            selectedIndex.value = index
            const field = localFields[index]
            
            // 获取元素和容器的精确位置信息
            const element = e.target.closest('.field-element')
            const containerRect = canvasContainer.value.getBoundingClientRect()
            const elementRect = element.getBoundingClientRect()
            
            // 记录初始状态（包含滚动位置）
            dragState.isDragging = true
            dragState.startX = e.clientX
            dragState.startY = e.clientY
            dragState.initialScrollX = canvasContainer.value.scrollLeft
            dragState.initialScrollY = canvasContainer.value.scrollTop
            dragState.elementOffsetX = elementRect.left - containerRect.left + dragState.initialScrollX
            dragState.elementOffsetY = elementRect.top - containerRect.top + dragState.initialScrollY
            dragState.initialFieldX = field.x
            dragState.initialFieldY = field.y
            
            document.addEventListener('mousemove', handleFieldDrag)
            document.addEventListener('mouseup', stopFieldDrag)
        }
        
        const handleFieldDrag = (e) => {
            if (!dragState.isDragging) return
            
            // 动态获取最新容器信息
            const containerRect = canvasContainer.value.getBoundingClientRect()
            const currentScrollX = canvasContainer.value.scrollLeft
            const currentScrollY = canvasContainer.value.scrollTop
            
            // 计算滚动偏移增量
            const scrollDeltaX = currentScrollX - dragState.initialScrollX
            const scrollDeltaY = currentScrollY - dragState.initialScrollY
            
            // 计算精确鼠标坐标（考虑当前滚动）
            const mouseX = e.clientX - containerRect.left + currentScrollX
            const mouseY = e.clientY - containerRect.top + currentScrollY
            
            // 计算基于初始位置的增量（补偿滚动偏移）
            const deltaX = mouseX - (dragState.elementOffsetX - scrollDeltaX)
            const deltaY = mouseY - (dragState.elementOffsetY - scrollDeltaY)
            
            const index = selectedIndex.value
            const field = localFields[index]
            const isImage = bgsx.value.fields?.[field.name]?.type === 'image'
            
            // 动态计算边界约束
            const maxX = canvasSize.width - (isImage ? field.width : 0)
            const maxY = canvasSize.height - (isImage ? field.height : 0)
            
            // 更新字段位置
            field.x = Math.max(0, Math.min(dragState.initialFieldX + deltaX, maxX))
            field.y = Math.max(0, Math.min(dragState.initialFieldY + deltaY, maxY))
            
            // 强制更新视图（解决滚动时的渲染延迟）
            canvasContainer.value.scrollLeft = currentScrollX
            canvasContainer.value.scrollTop = currentScrollY
        }
        
        // 键盘方向键移动位置
        const handleKeydown = (e) => {
            if (selectedIndex.value === -1) return
            const step = e.shiftKey ? 10 : 1
            const field = localFields[selectedIndex.value]
            switch(e.key) {
                case 'ArrowUp':
                    field.y = Math.max(0, field.y - step)
                    break
                case 'ArrowDown':
                    field.y = Math.min(canvasSize.height - (field.height || 0), field.y + step)
                    break
                case 'ArrowLeft':
                    field.x = Math.max(0, field.x - step)
                    break
                case 'ArrowRight':
                    field.x = Math.min(canvasSize.width - (field.width || 0), field.x + step)
                    break
                default: 
                    return
            }
            e.preventDefault()
        }

		const stopFieldDrag = () => {
			dragState.isDragging = false
			document.removeEventListener('mousemove', handleFieldDrag)
			document.removeEventListener('mouseup', stopFieldDrag)
		}

		// 调整大小
		const startResize = (index, e) => {
			selectedIndex.value = index
			Object.assign(currentField, localFields[index])
			dragState.isResizing = true
			dragState.startX = e.clientX
			dragState.startY = e.clientY
			dragState.originX = currentField.width
			dragState.originY = currentField.height
			document.addEventListener('mousemove', handleResize)
			document.addEventListener('mouseup', stopResize)
		}

		const handleResize = (e) => {
			if (!dragState.isResizing) return
			const deltaX = e.clientX - dragState.startX
			const deltaY = e.clientY - dragState.startY
            const current = localFields[selectedIndex.value]
            current.width = Math.max(10, dragState.originX + deltaX)
            current.height = Math.max(10, dragState.originY + deltaY)
		}

		const stopResize = () => {
			dragState.isResizing = false
			document.removeEventListener('mousemove', handleResize)
			document.removeEventListener('mouseup', stopResize)
		}

		// 数据保存到父组件
		const saveConfig = () => {
			const validationErrors = validateFields()
			if (validationErrors.length > 0) {
				ElMessage.error(validationErrors.join('\n'))
				return
			}
			emit('update', [...localFields])
			visible.value = false
		}

        const validateFields = () => {
            const errors = []
            localFields.forEach((field, index) => {
                if (!field.name) errors.push(`字段 #${index+1}: 名称不能为空`)
                if (field.x < 0 || field.x > canvasSize.width) errors.push(`字段 #${index+1}: X坐标应在0-${canvasSize.width}之间`)
                if (field.y < 0 || field.y > canvasSize.height) errors.push(`字段 #${index+1}: Y坐标应在0-${canvasSize.height}之间`)
                if (field.fontsize < 12 || field.fontsize > 72) errors.push(`字段 #${index+1}: 字号应在12-72之间`)
                const isImage = bgsx.value.fields?.[field.name]?.type === 'image'
                if (isImage && (!field.width || !field.height)) {
                    errors.push(`字段 #${index+1}: 图片字段需要设置宽高`)
                }
            })
            return errors
        }
        
		const getbgsx = (id) => {
			if (!id || !props.xmlist) return;
			const {xmlist, xmid} = props;
			const xm = xmlist.find(item => item.value.toString() === xmid?.toString());
			if (!xm?.fields) return;
			const {fields} = xm;
			const fieldEntries = Object.entries(fields);
			bgsx.value = xm;
			zdoptions.value = fieldEntries.map(([k, field]) => ({
				text: field.name || '未命名字段', // 添加默认值处理
				value: k
			}));
			usedValues.clear();
			fieldEntries.forEach(([k, field]) => {
				const value = field?.name?.trim(); // 使用可选链和去空格
				if (!value) {
					console.warn(`字段[${k}]缺少名称`);
					return;
				}
				if (usedValues.has(value)) {
					console.warn(`重复字段名: ${value} (键: ${k})`); // 添加键信息
				} else {
					usedValues.add(value);
				}
			});
		}
		
        // 同步使用记录
        const syncUsedValues = (fields) => {
            usedValues.clear()
            fields.forEach(field => {
                if (field.name) {
                    if (usedValues.has(field.name)) {
                        console.warn(`字段重复: ${field.name}`)
                    } else {
                        usedValues.add(field.name)
                    }
                }
            })
        }
        
        // 新增字段
        const addNewField = () => {
            // 查找第一个未使用的字段
            const availableField = zdoptions.value.find(opt => 
                !usedValues.has(opt.value) && 
                !localFields.some(f => f.name === opt.value)
            );
            if (!availableField) {
                ElMessage.warning('所有可用字段已添加完毕');
                smartSpeak('所有可用字段已添加完毕');
                return;
            }
            const fieldType = bgsx.value.fields?.[availableField.value]?.type;
            const newField = {
                name: availableField.value,
                x: 100,
                y: 100,
                fontcolor: '#000000',
                fontsize: 14,
                fontfamily: '宋体',
                width: 100, // 明确初始化图片字段宽高
                height: 100,
                textwidth: 300,  // 默认文本行宽
                rowheight: 24     // 默认行间距
            };
            localFields.push(newField);
            usedValues.add(newField.name);
            selectedIndex.value = localFields.length - 1;
        };

        // 删除当前选中字段
        const deleteCurrentField = () => {
            if (selectedIndex.value === -1) return;
            const deletedField = localFields[selectedIndex.value];
            localFields.splice(selectedIndex.value, 1);
            usedValues.delete(deletedField.name);
            selectedIndex.value = -1;
        };
        
        const getxmfields = (k) => {
            if(props.xmlist) {
                let xm = props.xmlist.find(item => String(item.value) === String(props.xmid));
                let xmfields = xm ? xm.fields : null;
                if(xmfields) {
                    return xmfields[k]?.name || k;
                }
            }
            return k;
        }
        
        // 字段同步watch
        watch(() => props.fields, (newVal) => {
            localFields.splice(0, localFields.length, ...JSON.parse(JSON.stringify(newVal.map(f => ({
                fontcolor: '#000000', // 默认颜色
                fontsize: 14,        // 默认字号
                fontfamily: '宋体', // 默认字体
                ...f
            })))));
            syncUsedValues(newVal); // 更新使用记录
        }, { immediate: true, deep: true });
        
		// 初始化
        watch(() => props.backgroundUrl, (newVal) => {
          if (newVal) initCanvasSize();
        }, { immediate: true })
        
		watch(() => props.xmid, async (newVal) => {
			if(newVal > 0) getbgsx(newVal);
		}, {
			immediate: true
		})

		return {
		    addNewField,
		    deleteCurrentField,
		    usedValues,
			visible,
			canvasContainer,
			canvasStyle,
			selectedIndex,
			activePanel,
			currentField,
			zdoptions,
			isImageField,
            getbgsx,
			getFieldStyle,
			startFieldDrag,
			startResize,
			saveConfig,
			syncUsedValues,
			localFields,
			handleKeydown,
			getxmfields
		}
    },
    
    template: `
<el-dialog v-model="visible" title="鼠标点击字段后可快速拖动位置，也可用键盘方向键精确移动" width="80%" top="5vh" class="field-config-dialog">
	<div class="config-container">
		<div class="canvas-container" ref="canvasContainer">
			<div class="canvas-wrapper" :style="canvasStyle">
				<div v-for="(field, index) in localFields" :key="field.name + index" class="field-element" :style="getFieldStyle(field)" :class="{ active: selectedIndex === index }" @mousedown="startFieldDrag(index, $event)">
					<div class="resize-handle" @mousedown.stop="startResize(index, $event)"></div>
					{{ getxmfields(field.name) }}
				</div>
			</div>
		</div>

		<div class="property-panel">
			<el-collapse v-model="activePanel">
				<el-collapse-item title="字段属性" name="field-props">
					<el-form label-width="100px">
                        <el-form-item label="字段操作">
                            <el-button type="primary" size="small" @click="addNewField":disabled="zdoptions.length === localFields.length">新增字段</el-button>
                            <el-button type="danger" size="small" @click="deleteCurrentField":disabled="selectedIndex === -1">删除选中</el-button>
                        </el-form-item>
						<el-form-item label="字段名称">
							<el-select v-model="currentField.name">
								<el-option v-for="item in zdoptions" :key="item.value" :label="item.text"
									:value="item.value" />
							</el-select>
						</el-form-item>

						<template v-if="!isImageField">
							<el-form-item label="字体" prop="fontfamily">
								<el-select v-model="currentField.fontfamily">
									<el-option v-for="font in fonts" :key="font.value" :label="font.text"
										:value="font.value" />
								</el-select>
							</el-form-item>

							<el-form-item label="字号" prop="fontsize">
								<el-slider v-model="currentField.fontsize" :min="12" :max="72"/>
							</el-form-item>

							<el-form-item label="颜色">
								<el-color-picker v-model="currentField.fontcolor" />
							</el-form-item>
						</template>

						<el-form-item label="位置坐标">
							<div class="position-inputs">
								<el-input-number v-model="currentField.x" :min="0" label="X">
								    <template #prefix><span>横X</span></template>
								</el-input-number>
								<el-input-number v-model="currentField.y" :min="0" label="Y">
								    <template #prefix><span>横X</span></template>
							    </el-input-number>
							</div>
						</el-form-item>

						<template v-if="isImageField">
							<el-form-item label="图片宽度" prop="width">
								<el-input-number v-model="currentField.width" :min="10" />
							</el-form-item>
							<el-form-item label="图片高度" prop="height">
								<el-input-number v-model="currentField.height" :min="10" />
							</el-form-item>
						</template>
						
                        <template v-else>
                            <el-form-item label="行宽">
                              <el-input-number v-model="currentField.textwidth" :min="0" :max="2000" />
                            </el-form-item>
                            <el-form-item label="行间距">
                              <el-input-number v-model="currentField.rowheight" :min="0" :max="100" />
                            </el-form-item>
                        </template>
					</el-form>
				</el-collapse-item>
				<el-collapse-item title="注意事项" name="field-props">
				    <b style="color:red">在此弹窗中点击保存后，要在主界面点击【保存配置】才会真正保存到后台。</b>
				</el-collapse-item>
			</el-collapse>
		</div>
	</div>

	<template #footer>
		<el-button @click="visible = false">取消</el-button>
		<el-button type="primary" @click="saveConfig">保存</el-button>
	</template>
</el-dialog>
    `
}